package com.gzhryc.shared_device.oem.h5.agent.mng.controllers.cdcz;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.data.dto.AjaxResult;
import com.gzhryc.common.data.dto.ListResult;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.DateBranchHelper;
import com.gzhryc.servlet.DtoConstants;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.enums.EPayState;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.base.models.OrderLogContent;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrder;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrderChargeLog;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrderDeviceLog;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrderLog;
import com.gzhryc.shared_device.cdcz.code.dao.enums.CDCZOrderEnum;
import com.gzhryc.shared_device.cdcz.code.dao.models.CDCZOrderDeviceLogContent;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderChargeLogService;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderDeviceLogService;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderLogService;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderService;
import com.gzhryc.shared_device.cdcz.code.services.dto.CDCZOrderSearch;
import com.gzhryc.shared_device.cdcz.core.ICDCZNetworkService;
import com.gzhryc.shared_device.cdcz.core.enums.ECDCZCostMode;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.oem.code.HttpNetworkServiceUtils;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.order.RedisCacheManager;
import com.gzhryc.shared_device.oem.code.order.event.OrderFinishEvent;
import com.gzhryc.shared_device.oem.code.profit.service.BusinessOrderService;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;
import com.gzhryc.shared_device.oem.h5.agent.mng.WebConstants;
import com.gzhryc.shared_device.oem.h5.agent.mng.dto.cdcz.ChargeSocketSlotInstantLogRecord;

public class ChargeSocketOrderController {

    static Logger log = Logger.getLogger(ChargeSocketOrderController.class);

    @Route("/cdcz/order/list.html")
    public String list(HttpServletRequest request) {
        request.setAttribute("payStateList", EPayState.values());
        request.setAttribute("stateList", CDCZOrderEnum.State.values());
        request.setAttribute("costModeList", ECDCZCostMode.values());
        request.setAttribute("dateBranchItemList", DateBranchHelper.self().getYearDateBranchItems());
        return "/cdcz/order/list.html";
    }

    @Route(value = "/cdcz/order/list.data")
    public ListResult<CDCZOrder> listData(HttpServletRequest request) {
        ListResult<CDCZOrder> result = new ListResult<>(DtoConstants.NULL_DATA, "暂无数据");
        CDCZOrderSearch search = WebUtils.getParameter(request, CDCZOrderSearch.class);
        String searchDate = WebUtils.getString(request,"searchDate");
        Integer pageNo = WebUtils.getInteger(request, "page", 1);
        Integer pageLimit = WebUtils.getInteger(request, "limit", WebConstants.PAGE_LIMIT);
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            search.setAgentId(loginUser.getId());
            try {
                if (StringUtils.isNotBlank(searchDate)) {
                    String[] strings = searchDate.split(" - ");
                    if (strings.length == 2) {
                        Date startDate = DateUtils.parseDate(strings[0], "yyyy-MM-dd");
                        Date endDate = DateUtils.parseDate(strings[1], "yyyy-MM-dd");
                        search.setStartDate(startDate);
                        search.setEndDate(endDate);
                    }
                }
                Date dateBranch = new Date();
                if (StringTools.isNotBlank(search.getDateBranchId())) {
                    dateBranch = DateBranchHelper.getDateByItemId(search.getDateBranchId());
                }

                result.getBody().setTotal(CDCZOrderService.self(dateBranch).countBySearch(search));
                List<CDCZOrder> data = CDCZOrderService.self(dateBranch).findBySearch(search, pageNo, pageLimit);
                if (data != null && data.size() > 0) {
                    result.setCode(DtoConstants.SUCCESS, null);
                    result.getBody().setData(data);
                }
            } catch (Exception e) {
                result.setMsg(e.getMessage());
            }
        }
        return result;
    }

    @Route("/cdcz/order/info.html")
    public String info(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                WebUtils.setAttribute(request, deviceOrder);
                if (EPayType.WXPay.index().equals(deviceOrder.getPayType())) {
                    WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
                    request.setAttribute("payOrder", payOrder);
                }
            }
        }
        return "/cdcz/order/info.html";
    }

    @Route(value = { "/cdcz/order/slot/instant_data/chart.data" })
    public AjaxResult chartData(HttpServletRequest request) {
        AjaxResult result = new AjaxResult(DtoConstants.NULL_DATA, "暂无数据");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            Date createDate = WebUtils.getDate(request, "createDate");
            if (createDate == null) {
                createDate = new Date();
            }
            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder == null) {
                return result;
            }
            if (deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                CDCZOrderDeviceLog deviceLog = CDCZOrderDeviceLogService.self(deviceOrder.getCreateDate()).getByTradeNo(tradeNo);
                if (deviceLog != null && JsonTools.isJsonStr(deviceLog.getContent())) {
                    Date startDate = deviceOrder.getStartDate();
                    Date endDate = deviceOrder.getEndDate() == null ? new Date() : deviceOrder.getEndDate();

                    endDate = DateUtils.addMinutes(endDate, 10);

                    Map<String, CDCZOrderDeviceLogContent.LogItem> data = new HashMap<>();
                    CDCZOrderDeviceLogContent deviceLogContent = JsonTools.fromJson(deviceLog.getContent(), CDCZOrderDeviceLogContent.class);
                    if (deviceLogContent != null && deviceLogContent.getItems() != null && deviceLogContent.getItems().size() > 0) {
                        for (CDCZOrderDeviceLogContent.LogItem item : deviceLogContent.getItems()) {
                            String key = DateFormatUtils.format(item.getDate(), "hh:mm");
                            data.put(key, item);
                        }
                    }
                    ChargeSocketSlotInstantLogRecord record = new ChargeSocketSlotInstantLogRecord();
                    CDCZOrderDeviceLogContent.LogItem upLogItem = null;
                    int count = 0;
                    while (startDate.before(endDate)) {
                        String time = DateFormatUtils.format(startDate, "hh:mm");
                        record.getTimes().add(time);
                        CDCZOrderDeviceLogContent.LogItem logItem = data.get(time);
                        if (logItem == null) {
                            if (count < 3) {
                                logItem = upLogItem;
                                count++;
                            }
                        } else {
                            upLogItem = logItem;
                            count = 0;
                        }

                        if (logItem != null) {
                            if (logItem.getInstantPower() != null) {
                                record.getPowerData().add(logItem.getInstantPower());
                            } else {
                                record.getPowerData().add(0.0);
                            }
                            if (logItem.getInstantCurrent() != null) {
                                record.getCurrentData().add(logItem.getInstantCurrent());
                            } else {
                                record.getCurrentData().add(0.0);
                            }
                        } else {
                            record.getPowerData().add(0.0);
                            record.getCurrentData().add(0.0);
                        }

                        startDate = DateUtils.addMinutes(startDate, 1);
                    }

                    result.setCode(DtoConstants.SUCCESS, null);
                    result.setBody(record);
                }
            } else {
                result.setCode(DtoConstants.NOT_POWER, "无权限查看");
            }
        }
        return result;
    }

    @Route("/cdcz/order/operate.html")
    public String operate(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                WebUtils.setAttribute(request, deviceOrder);
                if (EPayType.WXPay.index().equals(deviceOrder.getPayType())) {
                    WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
                    request.setAttribute("payOrder", payOrder);
                }
            }
        }
        return "/cdcz/order/operate.html";
    }

    @Route(value = "/cdcz/order/operate/record/list.data")
    public ListResult<OrderLogContent.LogItem> logListData(HttpServletRequest request) {
        ListResult<OrderLogContent.LogItem> result = new ListResult<>(DtoConstants.NULL_DATA, "暂无数据");
        String tradeNo = WebUtils.getString(request,"tradeNo");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if(loginUser != null && StringTools.isNotBlank(tradeNo)) {
            Date createDate = WebUtils.getDate(request,"createDate");
            if(createDate == null){
                createDate = new Date();
            }
            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                CDCZOrderLog orderLog = CDCZOrderLogService.self(createDate).getByTradeNo(tradeNo);
                if (orderLog != null && StringTools.isNotBlank(orderLog.getContent())) {
                    OrderLogContent logContent = JsonTools.fromJson(orderLog.getContent(), OrderLogContent.class);
                    if (logContent != null) {
                        result.setCode(DtoConstants.SUCCESS, null);
                        result.getBody().setData(logContent.getItems());
                    }
                }
            }else {
                result.setCode(DtoConstants.NOT_POWER,"无权限查看");
            }
        }
        return result;
    }

    @Route(value = "/cdcz/order/charge/record/list.data")
    public ListResult<OrderLogContent.LogItem> chargeLogListData(HttpServletRequest request) {
        ListResult<OrderLogContent.LogItem> result = new ListResult<>(DtoConstants.NULL_DATA, "暂无数据");
        String tradeNo = WebUtils.getString(request,"tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if(loginUser != null && StringTools.isNotBlank(tradeNo)) {
            if(createDate == null){
                createDate = new Date();
            }
            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                List<CDCZOrderChargeLog> orderLogList = CDCZOrderChargeLogService.self(createDate).findByTradeNo(tradeNo);
                if (orderLogList != null && orderLogList.size() > 0) {
                    result.setCode(DtoConstants.SUCCESS, null);
                    result.getBody().setData(new ArrayList<>());
                    for (CDCZOrderChargeLog chargeLog : orderLogList) {
                        if (JsonTools.isJsonStr(chargeLog.getContent())) {
                            OrderLogContent logContent = JsonTools.fromJson(chargeLog.getContent(), OrderLogContent.class);
                            if (logContent != null) {
                                result.getBody().getData().addAll(logContent.getItems());
                            }
                        }
                    }
                }
            }else {
                result.setCode(DtoConstants.NOT_POWER,"无权限查看");
            }
        }
        return result;
    }

    @Route("/cdcz/order/operate/refund.html")
    public String refund(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                request.setAttribute("refundMoneyStr", deviceOrder.getPayMoneyStr());
            }
        }
        return "/cdcz/order/refund.html";
    }

    @Route(value = {"/cdcz/order/operate/refund.do"})
    public AjaxResult doRefund(HttpServletRequest request, HttpSession session) {
        AjaxResult result = new AjaxResult(DtoConstants.EXECUTE_ERROR, "撤销订单失败");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Double refundMoneyStr = WebUtils.getDouble(request, "refundMoneyStr");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (refundMoneyStr == null) {
                result.setMsg("请填写退款金额");
                return result;
            }
            String refundNote = WebUtils.getString(request, "refundNote");
            if (StringTools.isBlank(refundNote)) {
                result.setMsg("请填写退款原因");
                return result;
            }
            Date createDate = WebUtils.getDate(request, "createDate");
            if (createDate == null) {
                createDate = new Date();
            }

            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getFullName());
                operateInfo.setOperateNote(refundNote);

                try {
                    int refundResult = CDCZOrderService.self(deviceOrder.getCreateDate()).refund(deviceOrder, NumberTools.changeMoney(refundMoneyStr),
                            PayServiceFactory.self(), operateInfo);
                    if (refundResult > 0) {
                        result.setCode(DtoConstants.SUCCESS, null);
                    }
                } catch (LogicException e) {
                    result.setMsg(e.getMessage());
                }
            } else {
                result.setCode(DtoConstants.NOT_POWER, "无权限操作");
            }
        }
        return result;
    }

    @Route(value = { "/cdcz/order/operate/cancel.html" })
    public String cancel(HttpServletRequest request) {
        return "/cdcz/order/cancel.html";
    }

    @Route(value = { "/cdcz/order/operate/cancel.do" })
    public AjaxResult doCancel(HttpServletRequest request) {
        AjaxResult result = new AjaxResult(DtoConstants.EXECUTE_ERROR, "撤销失败");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        String note = WebUtils.getString(request, "note");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (StringTools.isBlank(note)) {
                result.setMsg("请填撤销的原因");
                return result;
            }
            if (createDate == null) {
                createDate = new Date();
            }


            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                ICDCZNetworkService networkService = HttpNetworkServiceUtils.getCDCZNetworkService(deviceOrder.getIotId());

                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getFullName());
                operateInfo.setOperateNote("【撤销订单】" + note);

                Date cancelDate = new Date();

                try {
                    int cancelResult = CDCZOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder, PayServiceFactory.self(), networkService, operateInfo);
                    if (cancelResult > 0) {
                        //清理缓存，避免定时器重复处理
                        RedisCacheManager.removeWorkingCDCZDeviceOrder(deviceOrder.getTradeNo());
                        if (cancelResult == 2) {
                            deviceOrder = CDCZOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
                            //同步会员订单
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder.getTradeNo(), deviceOrder.getMoney()
                                    , deviceOrder.getPayMoney(), deviceOrder.getWalletMoney());
                            BusinessOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder.getTradeNo(), cancelDate);
                        }
                        result.setCode(DtoConstants.SUCCESS, null);
                    }
                } catch (LogicException e) {
                    result.setMsg(e.getMessage());
                }
            } else {
                result.setCode(DtoConstants.NOT_POWER, "无权限操作");
            }
        }
        return result;
    }

    @Route("/cdcz/order/operate/finish.html")
    public String finish(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }

            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                request.setAttribute("payMoneyStr", deviceOrder.getPayMoneyStr());
            }
        }
        return "/cdcz/order/finish.html";
    }

    @Route(value = { "/cdcz/order/operate/finish.do" })
    public AjaxResult doFinish(HttpServletRequest request) {
        AjaxResult result = new AjaxResult(DtoConstants.EXECUTE_ERROR, "完成失败");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Double payMoneyPrice = WebUtils.getDouble(request, "payMoneyStr");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (payMoneyPrice == null) {
                result.setMsg("请填写支付金额");
                return result;
            }
            if (createDate == null) {
                createDate = new Date();
            }

            CDCZOrder deviceOrder = CDCZOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder == null) {
                result.setMsg("未找到租借订单");
                return result;
            }

            if (deviceOrder.getAgentId() != null && deviceOrder.getAgentId().equals(loginUser.getId())) {
                ICDCZNetworkService networkService = HttpNetworkServiceUtils.getCDCZNetworkService(deviceOrder.getIotId());

                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getFullName());
                operateInfo.setOperateNote("后台代理操作完成订单");

                try {
                    int finishResult = CDCZOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder, NumberTools.changeMoney(payMoneyPrice), PayServiceFactory.self(),
                            networkService, operateInfo);
                    if (finishResult > 0) {
                        //清理缓存，避免定时器重复处理
                        RedisCacheManager.removeWorkingCDCZDeviceOrder(deviceOrder.getTradeNo());
                        if (finishResult == 2) {
                            deviceOrder = CDCZOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
                            //同步会员订单
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder.getTradeNo(), deviceOrder.getMoney(),
                                    deviceOrder.getPayMoney(), deviceOrder.getWalletMoney(),operateInfo);

                            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                            if (producer != null) {
                                OrderFinishEvent event = new OrderFinishEvent(EBusinessType.CDCZ.index(), deviceOrder.getTradeNo(), deviceOrder.getCreateDate(), operateInfo);
                                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
                                producer.send(kafkaMessage);
                            } else {
                                log.error("未初始化消息队列，订单{{0}}未触发完成事件", deviceOrder.getTradeNo());
                            }
                        }
                        result.setCode(DtoConstants.SUCCESS, null);
                    }
                } catch (LogicException e) {
                    result.setMsg(e.getMessage());
                }
            } else {
                result.setCode(DtoConstants.NOT_POWER, "无权限操作");
            }
        }
        return result;
    }
}
